import Moment from 'moment';
import AudioBlockInfo from './blocks/AudioBlockInfo';
import TextBlockInfo from './blocks/TextBlockInfo';
export const PROJECT_STORE_NAME = 'StudioProjectStore';
/**
 * database struct
 * StudioProjectStore
 *      ${videoId}
 *          items
 */
export default class StudioProject {
  public videoId: string;
  public name: string;
  public createDate = 0;
  public updateDate = 0;
  public db: IDBDatabase | null = null;
  public voiceList: Array<any>;
  public captionList: Array<any>;
  public flagList: Array<any>;
  constructor(videoId: string, name = 'untitled') {
    this.videoId = videoId;
    this.name = name;
    this.voiceList = [];
    this.captionList = [];
    this.flagList = [];
    this.createDate = Moment.now();
  }
  initDB(): Promise<IDBDatabase> {
    return new Promise((resolve, reject) => {
      const request = window.indexedDB.open(PROJECT_STORE_NAME);
      request.onerror = (error) => {
        reject(error);
      };
      request.onsuccess = () => {
        this.db = request.result;
        if (!this.db.objectStoreNames.contains(this.videoId)) {
          /**
           * update database version to add a video project container
           */
          const currentVersion = this.db.version;
          this.db.close();
          const newRequest = window.indexedDB.open(
            PROJECT_STORE_NAME,
            currentVersion + 1
          );
          newRequest.onsuccess = () => {
            this.db = newRequest.result;
            resolve(this.db);
            console.log('new request success');
          };
          newRequest.onupgradeneeded = (e: any) => {
            const dbInstance: IDBDatabase = e?.target.result as IDBDatabase;
            const objectStore = dbInstance.createObjectStore(this.videoId, {
              keyPath: 'name',
            });
            objectStore.createIndex('name', 'name', { unique: true });
          };
          newRequest.onerror = (error) => {
            reject(error);
          };
        } else {
          resolve(this.db);
        }
      };
      request.onupgradeneeded = (e: any) => {
        const dbInstance: IDBDatabase = e?.target.result as IDBDatabase;
        const objectStore = dbInstance.createObjectStore(this.videoId, {
          keyPath: 'name',
        });
        objectStore.createIndex('name', 'name', { unique: true });
      };
    });
  }
  getProjects() {
    return new Promise<Project[]>((resolve, reject) => {
      const store = this.db
        ?.transaction(this.videoId, 'readonly')
        .objectStore(this.videoId);
      if (store) {
        const req = store.getAll();
        req.onsuccess = () => {
          resolve(req.result);
        };
        req.onerror = (error) => {
          console.log(error);
          reject(error);
        };
      } else {
        reject(new Error('DB Not Found'));
      }
    });
  }
  storeProject(
    name: string,
    position: number,
    zoom: number,
    recordVol = 0,
    videoVol = 0
  ) {
    return new Promise((resolve, reject) => {
      const record: Project = {
        name: name,
        createDate: this.createDate,
        updateDate: this.updateDate,
        position: position,
        zoom: zoom,
        voiceList: this.voiceList,
        captionList: this.captionList,
        flagList: this.flagList,
        recordVolume: recordVol,
        videoVolume: videoVol,
      };
      const store = this.db!.transaction(this.videoId, 'readwrite').objectStore(
        this.videoId
      );
      const req = store.put(record);
      req.onsuccess = () => {
        resolve(record);
      };
      req.onerror = (error) => {
        reject(error);
      };
    });
  }
  storeVoiceList(list: any[]) {
    this.voiceList = list;
    this.updateDate = Moment.now();
  }
  storeCaptionList(list: any[]) {
    this.captionList = list;
    this.updateDate = Moment.now();
  }
  storeFlagList(list: Array<any>) {
    this.flagList = list;
    this.updateDate = Moment.now();
  }
  // async storeVideoData(videoBlob: Blob, audioBlob: Blob) {
  //   return await this.db.store(this.videoId, videoBlob, audioBlob);
  // }
  changeName(name: string) {
    this.name = name;
    this.updateDate = Moment.now();
  }
}
export interface Project {
  name: string;
  createDate: number;
  updateDate: number;
  position: number;
  zoom: number;
  voiceList: Array<any>;
  captionList: Array<any>;
  flagList: Array<any>;
  recordVolume: number;
  videoVolume: number;
}
export interface VoiceListItem {
  start: number;
  duration: number;
  options: any;
  blob: Blob;
}
